Rubyでできる!RISC-Vシミュレータの作りかた 〜 From 4649 To HELLO WORLD 〜
という記事を弊社の開発者ブログに書いたよ。
タイトルの変遷
最初のタイトルは「RISC-Vシミュレータの作り方」だったんだけど、パンチが弱いなーと思ってタイトルを色々こねくり回してた。以下はタイトルの変遷。
続・RISC-Vシミュレータの作り方
→ おRubyでも書けましてよ〜!RISC-Vシミュレータの作り方をご紹介いたしますわ〜!!
→ Rubyでできる!RISC-Vシミュレータの作りかた
→ 小さなRISC-Vシミュレータの作りかた
→ 自作RISC-VシミュレータからHELLO WORLD〜
→ Rubyでできる!RISC-Vシミュレータの作りかた 〜 From 4649 To HELLO WORLD 〜
CPUのエッセンスが詰め込まれてる
シンプルながらCPUのエッセンスが詰め込まれた良いものが出来た気がする。お褒めの言葉もいっぱいもらって大満足。
素敵なのでRustに移植してみよう
すごく良いと思いました!
コードもコンパクトにまとまってて、勉強によさそうです
メモリマップドI/Oを入れて良かった
実行結果をレジスタでしか確認できない時は微妙だなあと思ったけど、メモリマップドI/Oで出力できるようになったらグンと良くなった。入れて良かった〜
誰も最後まで読んでいない疑惑
はてなスター誰もつけてくれないんだよなー。長すぎて最後まで読んだ人が誰もいない疑惑。3部作にすれば良かったかなあ...
ライセンス
ライセンスはMITライセンスにした
手順は以下の通り
LICENSEファイルをリポジトリ内に配置
年と名前とメアドだけ書き換える
READMEに以下を追加
License
This software is released under the MIT License, see LICENSE.
Makefile
サンプルのビルドが大変だったのでMakefileを書いた
code:Makefile
roms = 4649.rom fibonacci.rom hello.rom loopback.rom
all: $(roms)
%.rom: %.elf
riscv64-unknown-elf-objcopy -O binary $< $@
%.elf: %.S
riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 -Wl,-Ttext=0x00 -nostdlib -o $@ $<
clean:
rm -rf *.elf *.rom
メモリのデータをStringとして保持
最初のメモリはIntegerの配列で持ってたんだけど、メモリは食うし操作しづらいしであまりうれしくない。
そういえばRubyってバイナリデータをStringで持ちがちだよなーと思ってStringにしてみたら、軽いし操作しやすいしで良いことだらけだった。
String#b
メモリからのデータ取得がうまくいかないなあと思ったら文字列のエンコーディングが Encoding::UTF-8 なのが原因だった。String#bを使って Encoding:ASCII-8BIT にしたらうまく取得できるようになった。
code:ruby
def initialize(data = "\0" * 512)
# バイナリデータとして扱いたいので ASCII-8BIT エンコーディングへ変換
@data = data.b
end
packとunpack
Stringなメモリからのデータのゲット・セットにpack・unpackが役に立った。こんな感じ。
code:ruby
def read(addr)
word = @data.slice(addr, WORD_SIZE)
word.unpack1("l")
end
def write(addr, word)
end
最初は「V: little endian unsigned 32bit」を使ってたんだけど、負の数も扱いたくなったので「l: int32_t(小文字のL)」を使うようにした。「l(小文字のL)」はエンディアンを指定できないんだけど、PowerPCを除く近代のPCはだいたいリトルエンディアンなので気にしなくても良さそう。
x0レジスタ
コードのコンパクトさを優先するため無理矢理な方法でx0で0を返すようにした。今回はコンパクトさ優先だから良いけど、普段こんなのは書いちゃダメだ。
code:ruby
@x_registers = 0 * 32 # レジスタ class << @x_registers
# x0は常に0を返す
def [](nth)
nth == 0 ? 0 : super
end
end
nop * 5
nopが5回連続来たらシミュレータを終了させるってなんか良いよね。
C言語対応
サンプルプログラムをC言語で書きたかったけど、命令が足りてなくて今回は見送り。あとで対応したいな。